#include "opcv.h"
#include "ui_opcv.h"

opcv::opcv(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::opcv),
    isRecording(false)
{
    ui->setupUi(this);
    setWindowState(Qt::WindowMaximized);

    classifier = CascadeClassifier("D:/opencv/opencv3.4-install/install/etc/haarcascades/haarcascade_frontalface_alt2.xml");

    vc.open(0);
    if(vc.isOpened())
    {
        qDebug() << "摄像头初始化成功，但尚未开始录像。";
        timer = new QTimer(this);

        connect(timer,SIGNAL(timeout()),this,SLOT(timeoutSlot()));
        connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(on_pushButton_clicked()));
    }
    else
    {
        qDebug() << "摄像头初始化失败！";
    }
    connect(ui->pushButton_2, SIGNAL(clicked()), this, SLOT(on_pushButton_2_clicked()));
    connect(ui->pushButton_3, SIGNAL(clicked()), this, SLOT(on_pushButton_3_clicked()));
}

opcv::~opcv()
{
    if(timer->isActive())
        timer->stop();
    delete ui;
}
/**
 * @brief Dialog::showSrc
 * 那么，如果你在 midSrc 上绘制了红框，而 midSrc 是从 src 中截取的，这就解释了为什么你在 src 上也能够看到红框。虽然 rectangle 函数是在 midSrc 上绘制的，但由于 midSrc 是从 src 中获取的一个子图像，midSrc 在这个过程中引用了 src 的数据，因此对 midSrc 的修改也会影响到 src。
 */
void opcv::showSrc()
{

    Mat rgb;
    cvtColor(src,rgb,CV_BGR2RGB);

    QImage img(rgb.data,//1.数据
               rgb.cols,//2.宽
               rgb.rows,//3.高
               rgb.cols*rgb.channels(),//4宽*通道数=每一行的总通道数
               QImage::Format_RGB888);//5.深度 cv_8u 0~255
    QPixmap p = QPixmap::fromImage(img);
    ui->label->setPixmap(p);
    ui->label->resize(QSize(p.size()));
}

void opcv::findFace()
{
    classifier.detectMultiScale(src,vec_findFaces);

    if(vec_findFaces.size()>0)
    {
        qDebug() << "人脸数：" << vec_findFaces.size();
        for(unsigned int i=0;i<vec_findFaces.size();i++)
        {
            Rect faceRect = vec_findFaces[i];
            // 画框
            rectangle(src,
                      faceRect, // 绘制的矩形范围
                      Scalar(0, 0, 255), // 绘制的矩形颜色BGR模式
                      2); // 线条粗细
        }
    }
}

void opcv::on_pushButton_clicked()
{
    if(!timer->isActive())
    {
        if(vc.isOpened())
        {
            qDebug() << "开始录像。";
            timer->start(50);
        }
        else
        {
            qDebug() << "摄像头打开失败，无法开始录像。";
        }
    }
}

void opcv::timeoutSlot()
{
    if(vc.grab()) // 尝试从摄像头抓取一帧图像
    {
        vc.retrieve(src); // 将抓取的图像存储到src中
        if(!src.empty())
        {
            findFace();
            showSrc();
        }
        else
        {
            qDebug() << "抓取的图像为空。";
        }
    }
    else
    {
        qDebug() << "无法从摄像头抓取图像。";
    }
}
void opcv::on_pushButton_2_clicked()
{
    if(!src.empty())
    {

        Mat rgb;
        cvtColor(src, rgb, CV_BGR2RGB);

        // Mat --> QImage
        QImage img(rgb.data, rgb.cols, rgb.rows, rgb.step, QImage::Format_RGB888);
        // QImage --> QPixmap
        QPixmap p = QPixmap::fromImage(img);
        ui->label_2->setPixmap(p);
        // 控件按照图像的大小进行显示
        ui->label_2->resize(QSize(p.size()));
    }
    else
    {
        qDebug() << "当前帧为空，无法截取。";
    }
}
void opcv::on_pushButton_3_clicked()
{
    if(timer->isActive())
    {
        qDebug() << "停止录像。";
        timer->stop(); // 停止定时器
        vc.release(); // 释放摄像头资源
        src.release(); // 清空图像资源
        // 清除视频画面
        ui->label->clear();

        // 尝试重新打开摄像头
        if (!vc.open(0))
        {
            qDebug() << "摄像头重新打开失败！";
        }
        else
        {
            qDebug() << "摄像头重新打开成功。";
        }
    }
}
